
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

public class SocketServerNIO {

    ServerSocketChannel server;

    Selector selector;

    private void initServer() {
        try {
            server = ServerSocketChannel.open();
            ServerSocketChannel server = ServerSocketChannel.open();
            server.configureBlocking(false);
            server.bind(new InetSocketAddress(9999));
            selector = Selector.open();
            server.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws Exception {
        new SocketServerNIO().start();
    }

    private void start() throws IOException, InterruptedException {
        initServer();
        System.out.println("服务器启动了。。。");

        while (true) {
            while (selector.select(1) > 0) {
                Thread.sleep(1500);
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                System.out.println("用户数据aaa");
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    try {
                        SelectionKey key = iterator.next();
                        //set集合remove，不然下一轮还会有这个key
                        iterator.remove();
                        if (key.isAcceptable()) {
                            handleAccept(key);
                        } else if (key.isReadable()) {
                            key.isReadable();
                            handleRead(key);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        }

    }

    private void handleAccept(SelectionKey key) throws IOException {
        //取出server channel
        ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
        SocketChannel client = ssc.accept();
        //设置client 非阻塞
        client.configureBlocking(false);
        ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
        //client注册selector,client key绑定buffer
        SelectionKey key1 = client.register(selector, SelectionKey.OP_READ, byteBuffer);
        System.out.println("新客户端连接。。。。。。" + client.getRemoteAddress());
    }

    private void handleRead(SelectionKey key) throws IOException {
        //client channel
        SocketChannel client = (SocketChannel) key.channel();
        //因为在selector注册时在client key上分配过byteBuffer
        ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
        try {
            while (true) {
                int read = 0;
                try {
                    read = client.read(byteBuffer);
                } catch (IOException e) {
                    client.close();
                    e.printStackTrace();
                    break;
                }
                System.out.println("用户数据到达。。。read:"+read);

                if (read > 0) {
                    //标记缓冲区字节的最后一个位置，并将指针移到起始位置
                    byteBuffer.flip();
                    String s = new String(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit(), StandardCharsets.UTF_8);
                    System.out.println(client.getRemoteAddress() + "客户端的消息：" + s);
                    client.write(byteBuffer);
                    byteBuffer.clear();
                } else if (read == 0) {
                    //读到为0的话，不需要处理，直接跳出本次handleRead
                    break;
                } else {
                    //-1可能客户端close_wait， 读到小于0的话次数超过10次，,关闭client
                    client.close();
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
